#pragma once

#include "VideoCapture.h"
#include <list>
#include <atomic>
#include <memory>
#include <vector>


#include "yolov8_det.hpp"

#include "ff_decode.hpp"
#include "ff_video_encode.h"
class sophonVideoCapture :public VideoCapture
{
public:
	sophonVideoCapture(const std::string& uri, const std::map<std::string, std::string>& opts = {});

	virtual ~sophonVideoCapture();

	/*VideoCapture callback*/
	virtual bool Start();

	virtual void Init(const char* devicename, int nWidth, int nHeight, int nFrameRate);

	virtual void Initdectect(const char* strJson);

	virtual void Stop(VideoYuvCallBack yuvCallback);

	virtual void Destroy();	
	

	virtual void RegisterCallback(VideoYuvCallBack yuvCallback);

	virtual void RegisterH264Callback(H264CallBack h264Callback) { m_h264Callback = h264Callback; };

	virtual bool onData(const char* id, unsigned char* buffer, int size, int64_t ts);

	virtual bool onData(uint8_t* y, int strideY, uint8_t* u, int strideU, uint8_t* v, int strideV, int nWidth, int nHeight, int64_t nTimeStamp) ;

	virtual bool decodercallback(uint8_t* y, int strideY, uint8_t* u, int strideU, uint8_t* v, int strideV, int nWidth, int nHeight, int64_t nTimeStamp);

	virtual bool isDectect() 
	{ 
		
#ifdef USE_YOLO
		if (m_objectDectect.get() != nullptr)
		{
			return m_objectDectect->isdetector();
		}
		else
		{
			return false;
	}
	
#endif

		return false;
	};

	virtual	const Json::Value detectorinfo(const Json::Value& jmessage);
	
	virtual void stopDetector()
	{

#ifdef USE_YOLO
		if (m_objectDectect.get() != nullptr)
		{
			m_objectDectect->stopDetector();
		}
#endif
	};
	virtual bool isPlay() { return true; };
	virtual void setCallbackEvent(MediaSourceEvent* callbackevent) {};
private:

	std::list<VideoYuvCallBack> m_YuvCallbackList;
	std::atomic<bool>			m_bStop;
	std::mutex					m_mutex;                //互斥锁	
	H264CallBack				m_h264Callback;
	std::string				    m_videourl;
	std::map<std::string, std::string> m_codec;

	int							m_nWidth = 0, m_nHeight = 0;
	int							m_nFrameRate = 30;
	int m_nError = 0;	

	std::atomic<bool> m_useNullCodec;

	VideoDecFFM *m_decoder;
	VideoEnc_FFMPEG *m_encoder=nullptr;

	bm_handle_t handle;
	std::vector<bm_image> batch_imgs;
	int batch_size;
	int64_t id = 0;
	
	YoloV8_det*yolov8;
	TimeStamp* ts;
	TimeStamp yolov8_ts;
	unsigned char* m_szEncodeBuffer = NULL;
	


	bool quit_flag = false;
	int is_rtsp;
	int width;
	int height;
	int coded_width;
	int coded_height;
	int pix_fmt;
	bool data_on_device_mem = true;

	int video_stream_idx;
	int refcount=0;
	// "101" for compressed and "0" for linear 
	int output_format = 0;
	AVCodec* decoder;
	//AVFrame* frame=nullptr;
	AVPacket pkt;
	AVFormatContext* ifmt_ctx=nullptr;

	AVCodecContext* video_dec_ctx;
	AVCodecParameters* video_dec_par;
	int openCodecContext(int* stream_idx, AVCodecContext** dec_ctx, AVFormatContext* fmt_ctx,
		enum AVMediaType type, int sophon_idx);
	int dev_id = 0;

	//AVFrame* yuvframe=nullptr;

};

